
#include "copyright.h"
#include "synch.h"
#include "system.h"
#include "time.h"
#include <iostream>


enum ManagerState{} managerState;
int goingOnBreak;

Condition *startMovieConditionVariable;
Condition *managerClerkGoingOnBreakConditionVariable;
Lock *managerLock;

/*int startMovieConditionVariable;
int managerClerkGoingOnBreakConditionVariable;
int managerLock;*/

bool runBreak;

void Manager()
{

	runBreak = true; //Set this to true to see manager tell ticketTaker to go on break
	int announceEarningsCounter = 0;
	if(THEATER_TESTS == 2) {
		announceEarningsCounter = 99999;
	}

	while (true)
	{
		//for(int i=0;i<5000;i++)
		//{
			//printf("Number of Customer %i\n",numberOfCustomers);
			currentThread->Yield();
		//}
		/*  */
		
		/*print out earnings*/
		if(announceEarningsCounter >= 50000) {
			int totalEarnings = 0;
			int totalTicketEarnings = 0;
			int totalFoodEarnings = 0;

			for(int i = 0; i < ticketClerks; i++) {
				
				ticketClerkLocks[i]->Acquire();
				
				/*LockAcquire(ticketClerkLocks[i]);*/
				totalEarnings += ticketEarnings[i];
				totalTicketEarnings += ticketEarnings[i];
				printf("Manager collected %i from TicketClerk %i\n", ticketEarnings[i], i);
				
				ticketClerkLocks[i]->Release();
				
				/*LockRelease(ticketClerkLocks[i]);*/
			}
			for(int i = 0; i < foodClerks; i++) {
				
				foodClerkLocks[i]->Acquire();
				
				/*LockAcquire(foodClerkLocks[i]);*/
				totalEarnings += foodEarnings[i];
				totalFoodEarnings += foodEarnings[i];
				printf("Manager collected %i from FoodClerk %i\n", foodEarnings[i], i);
				
				foodClerkLocks[i]->Release();
				
				/*LockRelease(foodClerkLocks[i]);*/
			}

			printf("Total money made by office = %i\n", totalEarnings);

			if(THEATER_TESTS == 2) {
				currentThread->Finish();
			}
			announceEarningsCounter = 0;

		}
		else {
			announceEarningsCounter++;
		}
		
		if(numberOfCustomers==0) /* */
		{
			printf("Theater is done\n");
			exit(0);
		}


		if(movieStarted==0&&ticketsTaken<=0&&takingTickets==false)
		{
			lobbyCV->Broadcast(lobbyLock);
			/*CVBroadcast(lobbyCV, lobbyLock);*/
			takingTickets=true;
		}



	//	printf("Custs Seated = %i\n\nTickets Taken = %i\n\n Movie Started = %i\n\n Taking Tickets = %i\n\nCustomers Remaining = %i \n\n Customers Served = %i\n\n",custsSeated,ticketsTaken,movieStarted,takingTickets,numberOfCustomers,customersServed);
		
		/*if(movieStarted=1&&techThreads->getStatus()==BLOCKED)
		{
			techManagerVariable->Signal(techLock);
		}*/

		/* Randomly starts the movie */

		if(takingTickets&&ticketsTaken>0)
		{
			int startMovieRandom;
			startMovieRandom = 0; /*Generate a random number to randomly start a movie*/
			if (startMovieRandom <1)
			{
				printf("Manager is telling the MovieTechnician to start the movie.\n");
				
				managerLock->Acquire();
				takingTicketsLock->Acquire();
				
				/*LockAcquire(managerLock);
				LockAcquire(takingTicketsLock);*/
					movieStarted = 1;
					takingTickets=false;
					
					techManagerVariable->Signal(techLock);
					
					/*CVSignal(techManagerVariable, techLock);*/
					
				takingTicketsLock->Release();
				managerLock->Release();
				
				/*LockRelease(takingTicketsLock);
				LockRelease(managerLock);*/
			}
		}
		/* If the employee lines are empty, then there is a 20% chance that the employee will go on break */
		if (runBreak == true)
		{
		
		ticketClerkLineLock->Acquire();
		
		/*LockAcquire(ticketClerkLineLock);*/
		for (int i=0; i < ticketClerks; i++)
		{
printf(">>>>>>>1\n");
			
			ticketClerkLocks[i]->Acquire();
			
			/*LockAcquire(ticketClerkLocks[i]);*/
			
			if (ticketClerkLineCount[i] == 0 && ticketClerkState[i]!=no_clerk && ticketClerkState[i]!=on_break && ticketClerkState[i]!=go_on_break) /*This will look for when there a clerk that isn't on break */
			{
printf(">>>>>>>2\n");
				goingOnBreak = rand() %10 + 1; /* Generates a random number used for determining whether the clerk is to go on break */
				if( goingOnBreak < 3) /* There is a 20% chance that the clerk will go on break */
				{
printf(">>>>>>>3\n");
					for(int j = 0; j<ticketClerks;j++)
					{
printf(">>>>>>>4\n");
						if(i!=j) /*  */
						{
printf(">>>>>>>5\n");
							/* Put the ticketClerk[i] that has zero customers in line on break */
							/*LockAcquire(ticketClerkLocks[j]);*/
							
							ticketClerkLocks[j]->Acquire();
							
							if (ticketClerkState[j]!=on_break && ticketClerkState[j]!=no_clerk && ticketClerkState[j]!=go_on_break) /* 20% chance that the ticketClerk will go on break */
							{
printf(">>>>>>>6\n");
							
								if (ticketClerkState[i]==available)
								{
printf(">>>>>>>7a\n");
									ticketClerkState[i] = on_break;
									
									ticketClerkConditionVariables[i]->Signal(ticketClerkLocks[i]); //Telling the clerk to go on break
									
									/*CVSignal(ticketClerkConditionVariables[i],ticketClerkLocks[i]);*/
printf("<<<<<<<7a\n");
								}
								else
								{
printf(">>>>>>>7b\n");
									ticketClerkState[i] = go_on_break;
printf("<<<<<<<7b\n");
								}
								printf("Manager has told TicketClerk %d to go on break.\n", i);
printf(">>>>>>>8\n");
								
								ticketClerkLocks[j]->Release();
								
								/*LockRelease(ticketClerkLocks[j]);*/
								
printf("<<<<<<<8\n");

								break;
printf("<<<<<<<6\n");
							}
							
							ticketClerkLocks[j]->Release();
							
							
							/*LockRelease(ticketClerkLocks[j]);*/

printf("<<<<<<<5\n");
						}
printf("<<<<<<<4\n");
					}

printf("<<<<<<<3\n");
				}

				

printf("<<<<<<<2\n");
			}
			
			ticketClerkLocks[i]->Release();
			
			/*LockRelease(ticketClerkLocks[i]);*/

printf("<<<<<<<1\n");
		}
		
		ticketClerkLineLock->Release();
		
		/*LockRelease(ticketClerkLineLock);*/

	}
		
		// for(int i=0;i<foodClerks;i++)
		// {

			// foodClerkLocks[i]->Acquire();
			// foodClerkLineLock->Acquire();
			// if (foodClerkLineCount[i] == 0 && foodClerkStates[i]!=no_clerk && foodClerkStates[i]!=on_break)
			// {
				// /* Put the foodClerk[i] that has zero customers in line on break */
				// goingOnBreak = rand() %10 + 1;
				// if (goingOnBreak < 3) /* 20% chance that the foodClerk will go on break */
				// {
					// for(int j = 0; j<foodClerks;j++)
					// {
						// goingOnBreak = rand() %10 + 1;
						// if(i!=j)
						// {
							// /* Put the ticketClerk[i] that has zero customers in line on break */
							// foodClerkLocks[j]->Acquire();
							// if ((foodClerkStates[j]!=on_break)&&(foodClerkStates[j]!=no_clerk) &&goingOnBreak < 3) /* 20% chance that the ticketClerk will go on break */
							// {

								// if (foodClerkStates[i]==available)
								// {
									// foodClerkStates[i] = on_break;
									// foodClerkConditionVariables[i]->Signal(foodClerkLocks[i]);
								// }
								// else
								// {
									// foodClerkStates[i] = go_on_break;
								// }
								
								// printf("Manager has told ConcessionClerk %d to go on break.\n", i);
								// foodClerkLocks[j]->Release();

								// break;
							// }
							// foodClerkLocks[j]->Release();
						// }
					// }


				// }
			// }
			// foodClerkLocks[i]->Release();
			// foodClerkLineLock->Release();
		// }
		// for (int i=0; i < ticketTakers; i++)
		// {
			// ticketTakerLineLock->Acquire();

			// ticketTakerLocks[i]->Acquire();
			// if ((ticketTakerLineCount[i] == 0)&& ticketTakerStates[i]!=no_clerk && ticketTakerStates[i]!=on_break)
			// {
				// goingOnBreak = rand() % 10 + 1;
					// if(goingOnBreak < 3)
					// {
						// for(int j = 0; j<ticketTakers;j++)
						// {
							// if(i!=j)
							// {
								// /* Put the ticketClerk[i] that has zero customers in line on break */
								// ticketTakerLocks[j]->Acquire();
								// if ((ticketTakerStates[j]!=on_break)&&(ticketTakerStates[j]!=no_clerk)) /* 20% chance that the ticketClerk will go on break */
								// {

									// if (ticketTakerStates[i]==available)
									// {
										// ticketTakerStates[i] = on_break;
										// ticketTakerConditionVariables[i]->Signal(ticketTakerLocks[i]);
									// }
									// else
									// {
										// ticketTakerStates[i] = go_on_break;
									// }
									// printf("Manager has told TicketTaker %d to go on break.\n", i);
									// ticketTakerLocks[j]->Release();

									// break;
								// }
								// ticketTakerLocks[j]->Release();
							// }
						// }
					// }
				// /* Put the ticketTaker[i] that has zero customers in line on break */
				// /* 20% chance that the ticketTaker will go on break */


			// }
			// ticketTakerLocks[i]->Release();
			// ticketTakerLineLock->Release();
		// }
		/*===============================================================================*/
		
		/*Checks if the ticketClerk have less than 3 employees and there is another person working*/
		/*If they do, then they have 20% of going on break*/
		// for (int i=0; i < ticketClerks; i++)
		// {
			// ticketClerkLocks[i]->Acquire();
			// ticketClerkLineLock->Acquire();
			// if ((ticketClerkLineCount[i] < 3)&&(ticketClerkState[i]!=on_break)) /* find a clerk that has less than 3 employees and isn't on break */ 
			// {
				
					// for (int j = 0; j < ticketClerks; j++)
					// {
						// if (j!=i) /* Find another clerk that isn't the same as the first clerk */
						// {
							// ticketClerkLocks[j]->Acquire();
							// if ((ticketClerkState[j]!=on_break)&&(ticketClerkState[j]!=no_clerk)) /* Check whether the second clerk is working. */
							// {
									// if (ticketClerkState[i]==available)
									// {
										// ticketClerkState[i] = on_break;
										// ticketClerkConditionVariables[i]->Signal(ticketClerkLocks[i]);
									// }
									// else
									// {
									// ticketClerkState[i] = go_on_break; /* If there is a second clerk working then the first clerk can go on break */
									// }
									// printf("Manager has told TicketClerk %d to go on break.\n", i);

									// ticketClerkLineConditionVariables[i]->Broadcast(ticketClerkLineLock); /* Tells all the customer in line of the first clerk that he is going on break*/
									// ticketClerkLocks[j]->Release();
									// break;																	/* They will all need to find a new line. Broadcasts to all ticketClerks */
									
							// }
							// ticketClerkLocks[j]->Release();
						// }
					// }
			// }
						// ticketClerkLineLock->Release();
						// ticketClerkLocks[i]->Release();
		// }
		
		// for (int i=0; i < foodClerks; i++)
		// {
			// foodClerkLineLock->Acquire();
			// foodClerkLocks[i]->Acquire();
			// if ((foodClerkLineCount[i] < 3)&&(foodClerkStates[i]!=on_break))
			// {
				// goingOnBreak = rand() % 10 + 1;
				// if(goingOnBreak < 3)
				// {
					// for (int j = 0; j < foodClerks; j++)
					// {
						// if (j!=i)
						// {
							// foodClerkLocks[j]->Acquire();
							// if ((foodClerkStates[j]!=on_break)&&(foodClerkStates[j]!=no_clerk))
							// {
									// if (foodClerkStates[i]==available)
									// {
										// foodClerkStates[i] = on_break;

										// foodClerkConditionVariables[i]->Signal(foodClerkLocks[i]);
									// }
									// else
									// {
									// foodClerkStates[i] = go_on_break;
									// }
									// printf("Manager has told ConcessionClerk %d to go on break.\n", i);

									// foodClerkLineConditionVariables[i]->Broadcast(foodClerkLineLock);
									// foodClerkLocks[j]->Release();
									// break;
							// }
							// foodClerkLocks[j]->Release();
						// }
					// }
				// }
			// }
			// foodClerkLineLock->Release();
			// foodClerkLocks[i]->Release();
		// }
		// for (int i=0; i < ticketTakers; i++)
		// {
			// ticketTakerLineLock->Acquire();
			// ticketTakerLocks[i]->Acquire();
			// if ((ticketTakerLineCount[i] < 3)&&(ticketTakerStates[i]!=on_break))
			// {
				// goingOnBreak = rand() % 10 + 1;
				// if(goingOnBreak < 3)
				// {
					// for (int j = 0; j < ticketTakers; j++)
					// {
						// if (j!=i)
						// {
							// ticketTakerLocks[j]->Acquire();
							// if ((ticketTakerStates[j]!=on_break)&&(ticketTakerStates[j]!=no_clerk))
							// {
									// if (ticketTakerStates[i]==available)
									// {
										// ticketTakerStates[i] = on_break;

										// ticketTakerConditionVariables[i]->Signal(ticketTakerLocks[i]);
									// }
									// else
									// {
									// ticketTakerStates[i] = go_on_break;
									// }
									// printf("Manager has told TicketTaker %d to go on break.\n", i);

									// ticketTakerLineConditionVariables[i]->Broadcast(ticketTakerLineLock);
									// ticketTakerLocks[j]->Release();
									// break;
							// }
							// ticketTakerLocks[j]->Release();
						// }
					// }
				// }
			// }
			// ticketTakerLineLock->Release();
			// ticketTakerLocks[i]->Release();
		// }
		/*============================================================================================*/
		///*If an employee has a line thats greater than 5, then an employee of the same type will get off break */
		
		// for (int i=0; i<ticketClerks; i++)
		// {
			// ticketClerkLineLock->Acquire();
			// if (ticketClerkLineCount[i] > 5) /* Looks for a clerk that has a line of more than 5 people */
			// {
				// for (int j=0; j<ticketClerks; j++) /* Looks for a second clerk that is on break */
				// {
					// if (j!=i) /* Makes sure that the first clerk isn't equal to the second clerk */
					// {
						// ticketClerkLocks[j]->Acquire();
						// if (ticketClerkState[j]==on_break)
						// {
							// ticketClerkState[j]=available; /* The clerk goes off break and gets back to work  */
							// ticketClerkConditionVariables[j]->Signal(ticketClerkLocks[j]);
							// ticketClerkLineConditionVariables[i]->Broadcast(ticketClerkLineLock); /* Broadcasts to everyone in the line of the first clerk that there is a new line available */
														// for (int k = 0; k < 10;k++)
								// {
															// printf("Manager has told TicketClerk %d to get off break.\n", i);

								// }
							// ticketClerkLocks[j]->Release();


							// break;
						// }
						// ticketClerkLocks[j]->Release();
					// }
				// }
			// }
			// ticketClerkLineLock->Release();
		// }
		
		

		// for (int i=0; i<foodClerks; i++)
		// {
			// foodClerkLineLock->Acquire();
			// if (foodClerkLineCount[i] > 5)
			// {
				// for (int j=0; j<foodClerks; j++)
				// {
					// if (j!=i)
					// {
						// foodClerkLocks[j]->Acquire();
						// if (foodClerkStates[j]==on_break)
						// {
							// foodClerkStates[j]=available;
							// foodClerkConditionVariables[j]->Signal(foodClerkLocks[j]);
							// foodClerkLineConditionVariables[i]->Broadcast(foodClerkLineLock);
							// foodClerkLocks[j]->Release();
							// break;
						// }
						// foodClerkLocks[j]->Release();
					// }
				// }
			// }
			// foodClerkLineLock->Release();
		// }
		
				
		// for (int i=0; i<ticketTakers; i++)
		// {
			// ticketTakerLineLock->Acquire();
			// if (ticketTakerLineCount[i] > 5)
			// {
				// for (int j=0; j<ticketTakers; j++)
				// {
					// if (j!=i)
					// {
						// ticketTakerLocks[j]->Acquire();
						// if (ticketTakerStates[j]==on_break)
						// {
							// ticketTakerStates[j]=available;		
							// ticketTakerConditionVariables[j]->Signal(ticketTakerLocks[j]);
							// ticketTakerLineConditionVariables[i]->Broadcast(ticketTakerLineLock);
							// ticketTakerLocks[j]->Release();
							// break;
						// }
						// ticketTakerLocks[j]->Release();
					// }
				// }
			// }
			// ticketTakerLineLock->Release();
			

		// }
		


		//ticketClerkLineLock->Release();			
		//foodClerkLineLock->Release();
		//ticketTakerLineLock->Release();
	
		if(THEATER_TESTS == 1)
			break;

	} /* While true */
}
